﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.Threading;
using AutoMapper;
using Core;
using IglooCoder.Commons.WcfNhibernate;
using Infrastucture;
using WcfService1.DTO;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" PurchaseOrder to change the class name "PurchaseOrderServices" in code, svc and config file together.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    [NHibernateContext]
    public class PurchaseOrderServices : IPurchaseOrderServices
    {
        private readonly PurchaseOrderRepository PurchaseOrderRepository;
        private readonly WcfSessionStorage _session;
        private readonly BTBRepository BtbRep;
        private readonly PurchaseInvoiceRepository PIRep;

        public PurchaseOrderServices()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            _session = new WcfSessionStorage();
            PurchaseOrderRepository = new PurchaseOrderRepository(_session);
            BtbRep = new BTBRepository(_session);
            PIRep= new PurchaseInvoiceRepository(_session);
        }

        #region IPurchaseOrderServices Members

        public List<PurchaseOrderDTO> GetList(int page, out long recordCount, string sortProperty = null,
                                              string sortType = "ASC")
        {
            var PurchaseOrders = new List<PurchaseOrder>();
            var Results = new List<PurchaseOrderDTO>();
            IList<PurchaseInvoice> PI = null;
            if (string.IsNullOrEmpty(sortProperty))
            {
                PurchaseOrders = PurchaseOrderRepository.GetDataPaged(page, 30, "PODate", "DESC").ToList();
            }
            else
            {
                PurchaseOrders = PurchaseOrderRepository.GetDataPaged(page, 30, sortProperty, sortType).ToList();
            }
            recordCount = PurchaseOrderRepository.RecordCount;
            PurchaseOrders.ForEach(x =>
                {

                    PurchaseOrderDTO PurchaseOrderDto = new PurchaseOrderDTO();
                    string NoBtb = string.Empty;
                    string NoPI = string.Empty;
                    if (x.Btbs.FirstOrDefault()!=null) NoPI = x.Btbs.FirstOrDefault().PINo;
                    foreach (var btb in x.Btbs)
                    {
                        NoBtb += "," + btb.NoBtb;
                       
                    }

                    PurchaseOrderDto.PODate = x.PODate;
                    PurchaseOrderDto.PONumber = x.PONumber;
                    PurchaseOrderDto.Description = x.Description;
                    PurchaseOrderDto.Discount = x.Discount;
                    PurchaseOrderDto.DiscountType = x.DiscountType;
                    PurchaseOrderDto.Ppn = x.Ppn;
                    PurchaseOrderDto.Supplier = new SupplierDTO() { SupplierId = x.Supplier.SupplierId, SupplierName = x.Supplier.SupplierName };
                    PurchaseOrderDto.Warehouse = new WarehouseDTO()
                                                     {
                                                         KodeWarehouse = x.Warehouse.KodeWarehouse,
                                                         WarehouseName = x.Warehouse.WarehouseName
                                                     };
                    PurchaseOrderDto.Currency = new CurrencyDTO()
                                                    {
                                                        CurrencyCode = x.Currency.CurrencyCode,
                                                        CurrencyName = x.Currency.CurrencyName
                                                    };
                    PurchaseOrderDto.Kurs = x.Kurs;
                    PurchaseOrderDto.Term = x.Term;
                    PurchaseOrderDto.TglTerimaBarang = x.TglTerimaBarang;
                    PurchaseOrderDto.Total = x.Total;
                    PurchaseOrderDto.Status = (Status)x.Status;
                    PurchaseOrderDto.NoBtb = NoBtb;
                    PurchaseOrderDto.NoPI = NoPI;
                    Results.Add(PurchaseOrderDto);
                }
             );
          
            return Results;
        }

        public bool Save(PurchaseOrderDTO PurchaseOrderDTO)
        {
            bool res;
            try
            {
                PurchaseOrderRepository.ExecuteTransactionNative(()=>
                                                                     {
                                                                         PurchaseOrder PurchaseOrder =
                                PurchaseOrderRepository.GetDataOne(x => x.PONumber == PurchaseOrderDTO.PONumber);
                                                                         var user = new User();
                                                                         if (PurchaseOrder == null)
                                                                         {
                                                                             PurchaseOrder = new PurchaseOrder();
                                                                             PurchaseOrderDTO.created_date = DateTime.Now;
                                                                             Mapper.Map(PurchaseOrderDTO, PurchaseOrder);
                                                                             //Untuk New entry dari transaksi bukan dari email
                                                                             if (String.IsNullOrEmpty(PurchaseOrder.PONumber))
                                                                                 PurchaseOrder.PONumber = GetLastPONo();
                                                                             foreach (var poDetail in PurchaseOrder.PurchaseOrderDetails)
                                                                             {
                                                                                 poDetail.PurchaseOrder = PurchaseOrder;
                                                                                 poDetail.PurchaseOrderDetailId = 0;
                                                                             }
                                                                             PurchaseOrderRepository.SaveOrUpdate(PurchaseOrder);
                                                                         }
                                                                         else
                                                                         {
                                                                             //Jika Status Void dan Close tdk boleh Update
                                                                             if (PurchaseOrder.Status == (int)Status.Void || PurchaseOrder.Status == (int)Status.Close)
                                                                                 throw new Exception("Tidak bisa di Update Status sudah Close atau Void!");
                                                                             PurchaseOrderRepository.Delete(PurchaseOrder);
                                                                             var PO = new PurchaseOrder();
                                                                             PO.modified_date = DateTime.Now;
                                                                             PO.created_date = PurchaseOrder.created_date;
                                                                             Mapper.Map(PurchaseOrderDTO, PO);
                                                                             foreach (var poDetail in PO.PurchaseOrderDetails)
                                                                                 poDetail.PurchaseOrder = PO;
                                                                             PurchaseOrderRepository.Session.SaveOrUpdateCopy(PO);
                                                                         }
            
                                                                     });
                
               
                res = true;
            }
            catch (Exception)
            {
                res = false;
                throw;
            }

            return res;
        }


        public bool Delete(PurchaseOrderDTO PurchaseOrderDto)
        {
            bool res;
            try
            {
                PurchaseOrder PurchaseOrder =
                    PurchaseOrderRepository.GetDataOne(x => x.PONumber == PurchaseOrderDto.PONumber);
                //PurchaseOrderRepository.Delete(PurchaseOrder);
                PurchaseOrder.Status = 2;
                PurchaseOrderRepository.SaveOrUpdate(PurchaseOrder);
                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public bool DeleteDetail(PurchaseOrderDetailDTO purchaseOrderDetail)
        {
            bool res;
            try
            {
                var PODetail = _session.GetSession().Get<PurchaseOrderDetail>(purchaseOrderDetail.PurchaseOrderDetailId);
                PurchaseOrderRepository.DeleteDetail(PODetail);
                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public List<PurchaseOrderDTO> GetListByCriteria(Dictionary<String, Object> criteria, string expression, int page,
                                                        out long recordCount)
        {
            var PurchaseOrders = new List<PurchaseOrder>();
            var Results = new List<PurchaseOrderDTO>();
            PurchaseOrders = PurchaseOrderRepository.GetDataPaged(criteria, expression, page, 30).ToList();
            recordCount = PurchaseOrderRepository.RecordCount;
            PurchaseOrders.ForEach(x =>
                                       {
                                           var PurchaseOrderDto = new PurchaseOrderDTO();
                                           Mapper.Map(x, PurchaseOrderDto);
                                           Results.Add(PurchaseOrderDto);
                                       }
                );

            return Results;
        }


        public List<PurchaseOrderDTO> GetAllPurchaseOrder()
        {
            IList<PurchaseOrder> PurchaseOrders =
                PurchaseOrderRepository.GetDataList(x => x.Status == Convert.ToInt16(Status.Open));
            IEnumerable<PurchaseOrderDTO> Results = PurchaseOrders.Select(x => new PurchaseOrderDTO
                                                                                   {
                                                                                       PONumber = x.PONumber
                                                                                   });

            return Results.ToList();
        }


        public PurchaseOrderDTO GetPurchaseOrder(String PONumber)
        {
            PurchaseOrder PurchaseOrder = PurchaseOrderRepository.GetDataOne(x => x.PONumber == PONumber);
            var PurchaseOrderDto = new PurchaseOrderDTO();
            Mapper.Map(PurchaseOrder, PurchaseOrderDto);
            return PurchaseOrderDto;
        }

        public List<PurchaseOrderDTO> GetPurchaseOrderList(string PONumber)
        {
            List<PurchaseOrder> PurchaseOrders =
                PurchaseOrderRepository.GetDataList(x => x.PONumber.Contains(PONumber)).ToList();
            var Results = new List<PurchaseOrderDTO>();
            PurchaseOrders.ForEach(x =>
                                       {
                                           var PurchaseOrderDto = new PurchaseOrderDTO();
                                           Mapper.Map(x, PurchaseOrderDto);
                                           Results.Add(PurchaseOrderDto);
                                       }
                );

            return Results;
        }


        public string GetLastPONo()
        {
            var appParamServices = new AppParamServices();
            AppParamDTO param = appParamServices.GetAppParamList("KodePO").FirstOrDefault();
            string res = PurchaseOrderRepository.GetMaxNumber(param.AppParamValue);
            
            if (string.IsNullOrEmpty(res))
                res = param.AppParamValue;

            string formatSO = "0000";
            string kodeSO;
            string lastNo = string.Empty;
            if (res.Length <= 4)
            {
                lastNo = formatSO;
                kodeSO = res;
            }
            else
            {
                lastNo = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[2];
                kodeSO = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0];
            }

            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(lastNo) + 1).ToString().Length) +
                           (int.Parse(lastNo) + 1);
            return kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
        }

        public bool SendEmail(PurchaseOrderDTO purchaseOrder, String DestinationFolder)
        {
            var mailServices = new MailServices();
            PurchaseOrder po = PurchaseOrderRepository.GetDataOne(x => x.PONumber == purchaseOrder.PONumber);
            purchaseOrder = Mapper.Map(po, purchaseOrder);
            return mailServices.SendEmail(purchaseOrder,DestinationFolder);
        }

        public void UpdateStatus(PurchaseOrderDTO purchaseOrder,Status status)
        {
            PurchaseOrderRepository.UpdateStatus(purchaseOrder.PONumber,(int)status);
        }

        #endregion
    }
}